home *** CD-ROM | disk | FTP | other *** search
/ Enigma Amiga Life 112 / EnigmaAmiga112CD.iso / dalla rivista / news / orbit / source / client.c < prev    next >
C/C++ Source or Header  |  2000-05-01  |  21KB  |  1,113 lines

  1. /*
  2.     Amiga port by Oliver Gantert
  3.  
  4.     27.04.2000 - fixed a lot of compiler warnings
  5. */
  6. /*
  7.  
  8. ORBIT, a freeware space combat simulator
  9. Copyright (C) 1999  Steve Belczyk <steve1@genesis.nred.ma.us>
  10.  
  11. This program is free software; you can redistribute it and/or
  12. modify it under the terms of the GNU General Public License
  13. as published by the Free Software Foundation; either version 2
  14. of the License, or (at your option) any later version.
  15.  
  16. This program is distributed in the hope that it will be useful,
  17. but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19. GNU General Public License for more details.
  20.  
  21. You should have received a copy of the GNU General Public License
  22. along with this program; if not, write to the Free Software
  23. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  24.  
  25. */
  26.  
  27. #include "orbit.h"
  28.  
  29. #ifndef AMIGA
  30. #ifndef WIN32
  31. #include <sys/socket.h>
  32. #include <unistd.h>
  33. #include <netinet/in.h>
  34. #include <netdb.h>
  35. #include <arpa/inet.h>
  36. #endif /* WIN32 */
  37. #include <fcntl.h>
  38. #endif /* AMIGA */
  39.  
  40. #include <errno.h>
  41. #include <limits.h>
  42. #include <stdarg.h>
  43.  
  44. /*
  45.  *  All sorts of stuff a client needs
  46.  */
  47.  
  48. int FindClient()
  49. /*
  50.  *  Find an unused client
  51.  */
  52. {
  53.   int c;
  54.  
  55.   for (c=0; c<NCLIENTS; c++)
  56.   {
  57.     if (!client[c].active)
  58.     {
  59.       client[c].active = 1;
  60.       return c;
  61.     }
  62.   }
  63.  
  64.   /* Ran out */
  65.   return (-1);
  66. }
  67.  
  68. void DoClient()
  69. /*
  70.  *  Handle ORBIT client duties
  71.  */
  72. {
  73. #ifndef AMIGA
  74.   char buf[1024];
  75.   int r, e;
  76.  
  77.   /* Bump timers */
  78.   clientme.timer.server += deltaT;
  79.   clientme.timer.pos += deltaT;
  80.  
  81.   /* If server has been idle too long, goodbye */
  82.   if (clientme.timer.server > MAXSERVERIDLE)
  83.   {
  84.     Mprint ("Server is not responding");
  85.     Log ("DoClient: Dropping idle server");
  86.     #ifndef WIN32
  87.     close (clientme.socket);
  88.     #else
  89.     closesocket (clientme.socket);
  90.     #endif
  91.     am_client = 0;
  92.     return;
  93.   }
  94.  
  95.   /* Time to report position? */
  96.   if (clientme.timer.pos >= CLIENTPOSINTERVAL)
  97.   {
  98.     ReportPosition();
  99.     clientme.timer.pos = 0.0;
  100.   }
  101.  
  102.   /* Try to read from the server */
  103.   r = recv (clientme.socket, buf, 1024, 0);
  104.  
  105.   /* If recv returns zero the other side has gone away */
  106.   if (r == 0)
  107.   {
  108.     Mprint ("Dropped by server");
  109.     Log ("DoClient: Dropped by server");
  110.     #ifndef WIN32
  111.     close (clientme.socket);
  112.     #else
  113.     closesocket (clientme.socket);
  114.     #endif
  115.     am_client = 0;
  116.  
  117.     InitNetwork();
  118.     InitTargets();
  119.  
  120.     return;
  121.   }
  122.  
  123.   /* If we get an error it better be EWOULDBLOCK */
  124.   #ifndef WIN32
  125.   if (r < 0)
  126.   {
  127.     if (errno == EWOULDBLOCK)
  128.     {
  129.       /* All is well, no data from server */
  130.       return;
  131.     }
  132.     else
  133.     {
  134.       /* Uh oh */
  135.       Log ("DoClient: recv() error: %d", errno);
  136.       return;
  137.     }
  138.   }
  139.   #else
  140.   if (r == SOCKET_ERROR)
  141.   {
  142.     e = WSAGetLastError();
  143.     if (e == WSAEWOULDBLOCK)
  144.     {
  145.       /* All is well, no data from server */
  146.       return;
  147.     }
  148.     else
  149.     {
  150.       /* Uh oh */
  151.       Log ("DoClient: recv() error: %d", e);
  152.       return;
  153.     }
  154.   }
  155.   #endif
  156.  
  157.   /* We really have data from the server! */
  158.   clientme.timer.server = 0.0;
  159.  
  160.   /* Handle the data */
  161.   buf[r] = 0;
  162.   recv_bytes += r;
  163.   /* Log ("DoClient: Server data: %s", buf); */
  164.  
  165.   ServerData (buf, r);
  166. #endif /* AMIGA */
  167. }
  168.  
  169. void ServerData (char *buf, int n)
  170. /*
  171.  *  Separate incoming data into packets
  172.  */
  173. {
  174.   int i;
  175.   #ifndef BINARYPACKETS
  176.   int ch, j;
  177.   #endif
  178.  
  179.   #ifdef BINARYPACKETS
  180.   for (i=0; i<n; i++) ServerByte (buf[i]);
  181.  
  182.   #else
  183.   j = clientme.ptr;
  184.  
  185.   for (i=0; i<n; i++)
  186.   {
  187.     ch = clientme.pkt[j] = buf[i];
  188.     j = (j + 1) % 1024;
  189.  
  190.     /* Got a packet? */
  191.     if (ch == 0)
  192.     {
  193.       ServerPacket (clientme.pkt);
  194.       j = 0;
  195.     }
  196.   }
  197.  
  198.   clientme.ptr = j;
  199.   #endif
  200. }
  201.  
  202. void ServerByte (char c)
  203. /*
  204.  *  Process one byte from server
  205.  */
  206. {
  207.   switch (clientme.state)
  208.   {
  209.     case NETSTATE_MAGIC:
  210.     if (c == NET_MAGIC)
  211.     {
  212.       clientme.state = NETSTATE_SIZE;
  213.     }
  214.     break;
  215.  
  216.     case NETSTATE_SIZE:
  217.     clientme.remain = 0xff & c;
  218.     clientme.ptr = 0;
  219.     clientme.state = NETSTATE_PACKET;
  220.     if (clientme.remain == 0) clientme.state = NETSTATE_MAGIC;
  221.     break;
  222.  
  223.     case NETSTATE_PACKET:
  224.     clientme.pkt[clientme.ptr++] = c;
  225.     clientme.remain--;
  226.     if (clientme.remain == 0)
  227.     {
  228.       clientme.pkt[clientme.ptr] = 0;
  229.       ServerPacket (clientme.pkt);
  230.       clientme.state = NETSTATE_MAGIC;
  231.     }
  232.     break;
  233.  
  234.     default:
  235.     Log ("ServerByte: PANIC! No such state: %d", clientme.state);
  236.     break;
  237.   }
  238. }
  239.  
  240. void ServerPacket (char *pkt)
  241. /*
  242.  *  Handle a packet from the server
  243.  */
  244. {
  245.   char cmd[128];
  246.  
  247.   /* If high bit of first byte is set, this is a binary packet */
  248.   if (0x80 & pkt[0])
  249.   {
  250.     ServerBinaryPacket (pkt);
  251.     return;
  252.   }
  253.  
  254.   /* Sanity check on packet */
  255.   if ( (strlen(pkt) == 0) ||
  256.   (pkt[0] == ' ') ||
  257.   (pkt[0] == '\r') ||
  258.   (pkt[0] == '\n') ||
  259.   (pkt[0] == '\t') )
  260.   {
  261.     Log ("ServerPacket: Insane packet: %s", pkt);
  262.     return;
  263.   }
  264.  
  265.   /* Extract command part */
  266.   sscanf (pkt, "%s", cmd);
  267.  
  268.   /* Dispatch */
  269.   if (!strcasecmp (cmd, "poss"))
  270.   {
  271.     ServerPositionShort (pkt);
  272.     return;
  273.   }
  274.   else if (!strcasecmp (cmd, "posl"))
  275.   {
  276.     ServerPositionLong (pkt);
  277.     return;
  278.   }
  279.   else if (!strcasecmp (cmd, "ping"))
  280.   {
  281.     ServerPing (pkt);
  282.     return;
  283.   }
  284.   else if (!strcasecmp (cmd, "fire"))
  285.   {
  286.     ServerFire (pkt);
  287.     return;
  288.   }
  289.   else if (!strcasecmp (cmd, "mhit"))
  290.   {
  291.     ServerMHit (pkt);
  292.     return;
  293.   }
  294.   else if (!strcasecmp (cmd, "mdie"))
  295.   {
  296.     ServerMDie (pkt);
  297.     return;
  298.   }
  299.   else if (!strcasecmp (cmd, "mesg"))
  300.   {
  301.     ServerMessage (pkt);
  302.     return;
  303.   }
  304.   else if (!strcasecmp (cmd, "name"))
  305.   {
  306.     ServerName (pkt);
  307.     return;
  308.   }
  309.   else if (!strcasecmp (cmd, "vcnt"))
  310.   {
  311.     ServerVacant (pkt);
  312.     return;
  313.   }
  314.   else if (!strcasecmp (cmd, "modl"))
  315.   {
  316.     ServerModel (pkt);
  317.     return;
  318.   }
  319.   else if (!strcasecmp (cmd, "flag"))
  320.   {
  321.     ServerFlag (pkt);
  322.     return;
  323.   }
  324.   else if (!strcasecmp (cmd, "crat"))
  325.   {
  326.     ServerCrater (pkt);
  327.     return;
  328.   }
  329.   else if (!strcasecmp (cmd, "cmsg"))
  330.   {
  331.     ServerCMSG (pkt);
  332.     return;
  333.   }
  334.   else if (!strcasecmp (cmd, "helo"))
  335.   {
  336.     ServerHelo (pkt);
  337.     return;
  338.   }
  339.   else if (!strcasecmp (cmd, "gbye"))
  340.   {
  341.     ServerGbye (pkt);
  342.     return;
  343.   }
  344.   else if (!strcasecmp (cmd, "welc"))
  345.   {
  346.     ServerWelcome (pkt);
  347.     return;
  348.   }
  349.   else if (!strcasecmp (cmd, "plan"))
  350.   {
  351.     ServerPlanet (pkt);
  352.     return;
  353.   }
  354.   else if (!strcasecmp (cmd, "rpln"))
  355.   {
  356.     ServerResetPlanets (pkt);
  357.     return;
  358.   }
  359.   else
  360.   {
  361.     Log ("ServerPacket: Unrecongized command: %s", cmd);
  362.     return;
  363.   }
  364. }
  365.  
  366. void ServerPing (char *pkt)
  367. /*
  368.  *  Handle ping packet from server
  369.  */
  370. {
  371.   /* Just send it right back */
  372.   SendASCIIPacket (clientme.socket, pkt);
  373. }
  374.  
  375. void ServerBinaryPing (char *pkt)
  376. /*
  377.  *  Handle binary ping packet
  378.  */
  379. {
  380.   double t;
  381.   
  382.   /* Decode */
  383.   DecodeBinaryPacket (pkt, "F", &t);
  384.   
  385.   /* Echo */
  386.   SendBinaryPacket (clientme.socket, "cF", PKT_PING, t);
  387. }
  388.  
  389. void ServerMessage (char *pkt)
  390. /*
  391.  *  Text message from server
  392.  */
  393. {
  394.   /* Print it to the screen */
  395.   if ( (pkt[4] != 0) && (pkt[5] != 0) )
  396.   {
  397.     Mprint (&pkt[5]);
  398.   }
  399. }
  400.  
  401. void ServerWelcome (char *pkt)
  402. /*
  403.  *  Server says hello and gives us our client number
  404.  */
  405. {
  406.   int i, t;
  407.  
  408.   /* Extract client number */
  409.   if (1 != sscanf (pkt, "%*s %d", &i)) return;
  410.  
  411.   /* Set up our client */
  412.   Log ("ServerWelcome: I am client %d", i);
  413.   clientme.client = i;
  414.  
  415.   /* Set up client and target */
  416.   client[i].active = 1;
  417.   client[i].is_me = 1;
  418.   client[i].frags = 0;
  419.   t = client[i].target = InitClientTarget();
  420.   strcpy (target[t].name, player.name);
  421.   target[t].hidden = target[t].invisible = 1;
  422. }
  423.  
  424. void ReportPosition()
  425. /*
  426.  *  Report my position
  427.  */
  428. {
  429.   #ifdef BINARYPACKETS
  430.   int c;
  431.   #else
  432.   char cmd[5];
  433.   #endif
  434.  
  435.   /* Not if we're dead */
  436.   if ( (state == STATE_DEAD1) || (state == STATE_DEAD2) ) return;
  437.  
  438.   /* Urgent? */
  439.   if (clientme.urgent)
  440.   {
  441.     #ifdef BINARYPACKETS
  442.     c = PKT_POSU;
  443.     #else
  444.     strcpy (cmd, "POSU");
  445.     #endif
  446.     clientme.urgent = 0;
  447.   }
  448.   else
  449.   {
  450.     #ifdef BINARYPACKETS
  451.     c = PKT_POSN;
  452.     #else
  453.     strcpy (cmd, "POSN");
  454.     #endif
  455.   }
  456.   
  457.   #ifdef BINARYPACKETS
  458.   SendBinaryPacket (clientme.socket, "cVVvvffffff", c,
  459.   player.pos, player.vel, player.view, player.up,
  460.   player.move_up, player.move_down,
  461.   player.move_right, player.move_left,
  462.   player.move_pitchright, player.move_pitchleft);
  463.   #else
  464.   SendASCIIPacket (clientme.socket,
  465.   "POSN %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf\n",
  466.      player.pos[0], player.pos[1], player.pos[2],
  467.      player.vel[0], player.vel[1], player.vel[2],
  468.      player.view[0], player.view[1], player.view[2],
  469.      player.up[0], player.up[1], player.up[2],
  470.   player.move_up, player.move_down,
  471.   player.move_right, player.move_left,
  472.   player.move_pitchright, player.move_pitchleft);
  473. #endif
  474. }
  475.  
  476. void ServerPositionShort (char *pkt)
  477. /*
  478.  *  The server is sending a client's short position report
  479.  */
  480. {
  481.  int c;
  482.  double pos[3], vel[3];
  483.  
  484.  /* Parse packet */
  485.  if (7 != sscanf (pkt, "%*s %d %lf %lf %lf %lf %lf %lf", &c,
  486.   &player.pos[0], &player.pos[1], &player.pos[2],
  487.   &player.vel[0], &player.vel[1], &player.vel[2]))
  488.  {
  489.   Log ("ServerPositionShort: Malformed POSS packet: %s", pkt);
  490.   return;
  491.  }
  492.  
  493.  PositionShort (c, pos, vel);
  494. }
  495.  
  496. void PositionShort (int c, double *pos, double *vel)
  497. /*
  498.  *  Process short position report
  499.  */
  500. {
  501.  int t;
  502.  
  503.  /* Sanity */
  504.  if ((c<0) || (c>=NCLIENTS)) return;
  505.  
  506.  /* Mark client active */
  507.  client[c].active = 1;
  508.  
  509.  /* Is it for me? */
  510.  if (client[c].is_me)
  511.  {
  512.   Vset (player.pos, pos);
  513.   Vset (player.vel, vel);
  514.  }
  515.  else
  516.  {
  517.   /* Not for me, see if we have target for this client */
  518.   if ((-1) == (t = client[c].target))
  519.   {
  520.    t = client[c].target = InitClientTarget();
  521.   }
  522.  
  523.   /* Make target unhidden */
  524.   target[t].hidden = 0;
  525.  
  526.   /* Set position */
  527.   Vset (target[t].pos, pos);
  528.   Vset (target[t].vel, vel);
  529.  }
  530. }
  531.  
  532. void ServerPositionLong (char *pkt)
  533. /*
  534.  *  The server is sending a client's long position report
  535.  */
  536. {
  537.  int c;
  538.  double pos[3], vel[3], view[3], up[3], move_up, move_down, move_left;
  539.  double move_right, move_pitchright, move_pitchleft;
  540.  
  541.  /* Parse packet */
  542.  if (19 != sscanf (pkt, "%*s %d %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf",
  543.   &c,
  544.   &pos[0], &pos[1], &pos[2], &vel[0], &vel[1], &vel[2],
  545.   &view[0], &view[1], &view[2], &up[0], &up[1], &up[2],
  546.   &move_up, &move_down, &move_right, &move_left,
  547.   &move_pitchright, &move_pitchleft))
  548.  {
  549.   Log ("ServerPositionLong: Malformed POSL packet: %s", pkt);
  550.   return;
  551.  }
  552.  
  553.  PositionLong (c, pos, vel, view, up, move_up, move_down, move_right,
  554.   move_left, move_pitchright, move_pitchleft);
  555. }
  556.  
  557. void PositionLong ( int c, double *pos, double *vel, double *view, double *up,
  558.                     double move_up, double move_down, double move_right, double move_left,
  559.                     double move_pitchright, double move_pitchleft )
  560. /*
  561.  *  Process a long position report
  562.  */
  563. {
  564.  int t;
  565.  
  566.  /* Sanity */
  567.  if ((c<0) || (c>=NCLIENTS)) return;
  568.  
  569.  /* Mark client active */
  570.  client[c].active = 1;
  571.  
  572.  /* Is it for me? */
  573.  if (client[c].is_me)
  574.  {
  575.   Vset (player.pos, pos);
  576.   Vset (player.vel, vel);
  577.   Vset (player.view, view);
  578.   Vset (player.up, up);
  579.   player.move_up = move_up;
  580.   player.move_down = move_down;
  581.   player.move_left = move_left;
  582.   player.move_right = move_right;
  583.   player.move_pitchright = move_pitchright;
  584.   player.move_pitchleft = move_pitchleft;
  585.   Crossp (player.right, player.up, player.view);
  586.  }
  587.  else
  588.  {
  589.   /* Not for me, see if we have target for this client */
  590.   if ((-1) == (t = client[c].target))
  591.   {
  592.    t = client[c].target = InitClientTarget();
  593.   }
  594.  
  595.   /* Make target unhidden */
  596.   target[t].hidden = 0;
  597.  
  598.   /* Set position */
  599.   Vset (target[t].pos, pos);
  600.   Vset (target[t].vel, vel);
  601.   Vset (target[t].view, view);
  602.   Vset (target[t].up, up);
  603.   target[t].move_up = move_up;
  604.   target[t].move_down = move_down;
  605.   target[t].move_left = move_left;
  606.   target[t].move_right = move_right;
  607.   target[t].move_pitchright = move_pitchright;
  608.   target[t].move_pitchleft = move_pitchleft;
  609.  
  610.   Normalize (target[t].up);
  611.   Normalize (target[t].view);
  612.  
  613.   Crossp (target[t].right, target[t].up, target[t].view);
  614.  }
  615. }
  616.  
  617. void ServerMHit (char *pkt)
  618. /*
  619.  *  We were hit by a missile
  620.  */
  621. {
  622.  double yield;
  623.  
  624.  /* Parse packet */
  625.  if (1 != sscanf (pkt, "%*s %lf", &yield))
  626.  {
  627.   Log ("ServerMHit: Malformed MHIT packet: %s", pkt);
  628.   return;
  629.  }
  630.  
  631.  /* Flash screen red */
  632.  palette_flash = 2;
  633.  
  634.  /* Damage shields */
  635.  player.shields -= yield;
  636.  if (player.shields < 0.0) player.shields = 0.0;
  637. }
  638.  
  639. void ServerMDie (char *pkt)
  640. /*
  641.  *  Someone was killed.  Hope it wasn't me!
  642.  */
  643. {
  644.  int ckiller, cvictim;
  645.  double v[3], d;
  646.  
  647.  /* Parse packet */
  648.  if (2 != sscanf (pkt, "%*s %d %d", &cvictim, &ckiller))
  649.  {
  650.   Log ("ServerMDie: Malformed MDIE packet: %s", pkt);
  651.   return;
  652.  }
  653.  
  654.  /* Adjust frags */
  655.  client[ckiller].frags++;
  656.  
  657.  /* Tell me about it */
  658.  Cprint ("%s was killed by %s",
  659.   target[client[cvictim].target].name,
  660.   target[client[ckiller].target].name);
  661.  
  662.  /* Was it me? */
  663.  if (cvictim == clientme.client)
  664.  {
  665.   Cprint ("YOU were killed!");
  666.   NetPlayerDies();
  667.  }
  668.  else
  669.  {
  670.   /* Make target hidden */
  671.   target[client[cvictim].target].hidden = 1;
  672.  
  673.   /* Make a boom if close enough */
  674.   Vsub (v, player.pos, target[client[cvictim].target].pos);
  675.   d = Mag2 (v);
  676.   if (d <= TARG_MAXRANGE2) Boom (target[client[cvictim].target].pos, 1.0);
  677.  }
  678.  
  679.  CheckLock();
  680. }
  681.  
  682. void ServerCrater (char *pkt)
  683. /*
  684.  *  Someone hit a planet.  Hope it wasn't me!
  685.  */
  686. {
  687.  int c, p;
  688.  double v[3], d;
  689.  
  690.  /* Parse packet */
  691.  if (2 != sscanf (pkt, "%*s %d %d", &c, &p))
  692.  {
  693.   Log ("ServerMDie: Malformed CRAT packet: %s", pkt);
  694.   return;
  695.  }
  696.  
  697.  /* Adjust frags */
  698.  client[c].frags--;
  699.  
  700.  /* Tell me about it */
  701.  Cprint ("%s cratered on %s",
  702.   target[client[c].target].name, planet[p].name);
  703.  
  704.  /* Was it me? */
  705.  if (c == clientme.client)
  706.  {
  707.   NetPlayerDies();
  708.  }
  709.  else
  710.  {
  711.   /* Make target hidden */
  712.   target[client[c].target].hidden = 1;
  713.  
  714.   /* Make a boom if close enough */
  715.   Vsub (v, player.pos, target[client[c].target].pos);
  716.   d = Mag2 (v);
  717.   if (d <= TARG_MAXRANGE2) Boom (target[client[c].target].pos, 1.0);
  718.  }
  719.  
  720.  CheckLock();
  721. }
  722.  
  723. void ServerFire (char *pkt)
  724. /*
  725.  *  Someone nearby has fired a missile
  726.  */
  727. {
  728.  int c, t, w;
  729.  
  730.  /* Parse packet */
  731.  if (2 != sscanf (pkt, "%*s %d %d", &c, &w))
  732.  {
  733.   Log ("ServerFire: Malformed FIRE packet: %s", pkt);
  734.   return;
  735.  }
  736.  
  737.  /* Get target for this client */
  738.  t = client[c].target;
  739.  
  740.  /* Fire the missile! */
  741.  FireMissile (target[t].pos, target[t].vel, target[t].view,
  742.   0, w, t);
  743. }
  744.  
  745. void ServerPlanet (char *pkt)
  746. /*
  747.  *  Server sends the position of a planet
  748.  */
  749. {
  750.  int p;
  751.  double theta;
  752.  
  753.  /* Parse packet */
  754.  if (2 != sscanf (pkt, "%*s %d %lf", &p, &theta))
  755.  {
  756.   Log ("ServerPlanet: Malformed PLAN packet: %s", pkt);
  757.   return;
  758.  }
  759.  
  760.  if ((p >= 0) && (p < NPLANETS)) planet[p].theta = theta;
  761. }
  762.  
  763. void ServerBinaryPlanet (char *pkt)
  764. /*
  765.  *  Server sends the position of a planet in binary
  766.  */
  767. {
  768.  int p;
  769.  double theta;
  770.  
  771.  /* Parse packet */
  772.  DecodeBinaryPacket (pkt, "cF", &p, &theta);
  773.  
  774.  /* Set planet angle */
  775.  if ((p >= 0) && (p < NPLANETS)) planet[p].theta = theta;
  776. }
  777.  
  778. void ServerResetPlanets (char *pkt)
  779. /*
  780.  *  Server done sending planet positions
  781.  */
  782. {
  783.  PositionPlanets();
  784. }
  785.  
  786. void ServerName (char *pkt)
  787. /*
  788.  *  Server sends us the name of an active client
  789.  */
  790. {
  791.  int c, t, f;
  792.  char buf[256];
  793.  
  794.  /* Parse packet */
  795.  if (3 != sscanf (pkt, "%*s %d %s %d", &c, buf, &f))
  796.  {
  797.   Log ("ServerName: Malformed NAME packet: %s", pkt);
  798.   return;
  799.  }
  800.  
  801.  /* Sanity check */
  802.  if ((c<0) || (c>=NCLIENTS)) return;
  803.  
  804. /* Log ("ServerName: NAME %d %s %d", c, buf, f); */
  805.  
  806.  /* Don't bother if it's us */
  807.  if (c == clientme.client)
  808.  {
  809.   client[c].frags = f;
  810.   return;
  811.  }
  812.  
  813.  /* Show client is active */
  814.  client[c].active = 1;
  815.  
  816.  /* Set up a target if we didn't know about this one */
  817.  if ((-1) == (t = client[c].target))
  818.  {
  819.   t = InitClientTarget();
  820.   client[c].target = t;
  821.  }
  822.  
  823.  /* Set name and frags */
  824.  strcpy (target[t].name, buf);
  825.  client[c].frags = f;
  826. }
  827.  
  828. void ServerHelo (char *pkt)
  829. /*
  830.  *  A new client has joined the game
  831.  */
  832. {
  833.  int c, t;
  834.  char buf[256];
  835.  
  836.  /* Parse packet */
  837.  if (2 != sscanf (pkt, "%*s %d %s", &c, buf))
  838.  {
  839.   Log ("ServerName: Malformed HELO packet: %s", pkt);
  840.   return;
  841.  }
  842.  
  843.  /* Sanity check */
  844.  if ((c<0) || (c>=NCLIENTS)) return;
  845.  
  846.  /* Tell us */
  847.  Cprint ("%s is here", buf);
  848.  Log ("ServerHelo: HELO %d %s", c, buf);
  849.  
  850.  /* Don't bother if it's us */
  851.  if (c == clientme.client) return;
  852.  
  853.  /* Set up a target if we didn't know about this one */
  854.  if ((-1) == (t = client[c].target))
  855.  {
  856.   t = InitClientTarget();
  857.   client[c].target = t;
  858.  }
  859.  
  860.  /* Set name */
  861.  strcpy (target[t].name, buf);
  862. }
  863.  
  864. void ServerVacant (char *pkt)
  865. /*
  866.  *  Server tells us about an unused client slot
  867.  */
  868. {
  869.  int c;
  870.  
  871.  /* Parse packet */
  872.  if (1 != sscanf (pkt, "%*s %d", &c))
  873.  {
  874.   Log ("ServerVacant: Malformed VCNT packet: %s", pkt);
  875.   return;
  876.  }
  877.  
  878.  if ((c<=0) || (c>=NCLIENTS)) return;
  879.  
  880.  Log ("ServerVacant: VCNT %d", c);
  881.  
  882.  /* Don't bother if it's us (this should never happen!) */
  883.  if (c == clientme.client)
  884.  {
  885.   Log ("ServerVacant: PANIC! Server says I am vacant!");
  886.   return;
  887.  }
  888.  
  889.  /* Destroy any associated target */
  890.  if ((-1) != client[c].target) DestroyTarget (client[c].target);
  891.  client[c].active = 0;
  892.  client[c].target = (-1);
  893. }
  894.  
  895. void ServerGbye (char *pkt)
  896. /*
  897.  *  Someone has left the game
  898.  */
  899. {
  900.  int c;
  901.  char buf[256];
  902.  
  903.  /* Parse packet */
  904.  if (2 != sscanf (pkt, "%*s %d %s", &c, buf))
  905.  {
  906.   Log ("ServerVacant: Malformed GBYE packet: %s", pkt);
  907.   return;
  908.  }
  909.  
  910.  if ((c<=0) || (c>=NCLIENTS)) return;
  911.  
  912.  Log ("ServerGbye: GBYE %d", c);
  913.  
  914.  /* Don't bother if it's us (this should never happen!) */
  915.  if (c == clientme.client)
  916.  {
  917.   Log ("ServerGbye: PANIC! Server says I am gone!");
  918.   return;
  919.  }
  920.  
  921.  /* Tell us */
  922.  Cprint ("%s is gone", buf);
  923.  
  924.  /* Destroy any associated target */
  925.  if ((-1) != client[c].target) DestroyTarget (client[c].target);
  926.  client[c].active = 0;
  927.  client[c].target = (-1);
  928. }
  929.  
  930. void ServerCMSG (char *pkt)
  931. /*
  932.  *  Server has a console message for us
  933.  */
  934. {
  935.  /* Sanity */
  936.  if ( (pkt[4] == 0) || (pkt[5] == 0) ) return;
  937.  
  938.  /* Show it */
  939.  Cprint ("%s", &pkt[5]);
  940.  
  941.  /* Give the sound */
  942.  if (sound) PlayAudio (SOUND_COMM);
  943. }
  944.  
  945. void ServerFlag (char *pkt)
  946. /*
  947.  *  Game flags from server
  948.  */
  949. {
  950.  int f;
  951.  
  952.  /* Parse packet */
  953.  if (1 != sscanf (pkt, "%*s %d", &f))
  954.  {
  955.   Log ("ServerFlag: Malformed FLAG packet: %s", pkt);
  956.   return;
  957.  }
  958.  
  959.  /* Set flags */
  960.  gravity = (f & FLAG_GRAVITY) ? 1 : 0;
  961.  player.flightmodel = (f & FLAG_FLIGHTMODEL) ? FLIGHT_ARCADE : FLIGHT_NEWTONIAN;
  962.  fullstop = (f & FLAG_FULLSTOP) ? 1 : 0;
  963.  realdistances = (f & FLAG_REALDISTANCES) ? 1 : 0;
  964.  orbit = (f & FLAG_ORBIT) ? 1 : 0;
  965. }
  966.  
  967. void DoConnect ()
  968. /*
  969.  *  Sparky has finished typing the server address
  970.  */
  971. {
  972.  BecomeClient (text.buf);
  973. }
  974.  
  975. void ServerModel (char *pkt)
  976. /*
  977.  *  Set client model
  978.  */
  979. {
  980.  char buf[128];
  981.  int m, c;
  982.  
  983.  /* Parse packet */
  984.  if (2 != sscanf (pkt, "%*s %d %s", &c, buf))
  985.  {
  986.   Log ("ServerModel: Malformed MODL packet: %s", pkt);
  987.   return;
  988.  }
  989.  
  990.  /* Sanity */
  991.  if ( (c < 0) || (c >= NCLIENTS) || (!client[c].active) || (client[c].is_me) ) return;
  992.  
  993.  /* Try to load model */
  994.  m = LoadModel (buf);
  995.  
  996.  /* Success? */
  997.  if (m != (-1))
  998.  {
  999.   target[client[c].target].model = m;
  1000.   target[client[c].target].list = model[m].list;
  1001.  }
  1002.  else
  1003.  {
  1004.   Log ("ServerModel: LoadModel (%s) failed", buf);
  1005.   /* Use default model */
  1006.   m = LoadModel ("light2.tri");
  1007.   target[client[c].target].model = m;
  1008.   target[client[c].target].list = model[m].list;
  1009.  }
  1010. }
  1011.  
  1012. void ServerBinaryPacket (unsigned char *pkt)
  1013. /*
  1014.  *  Handle binary packet from server
  1015.  */
  1016. {
  1017.  /* Dispatch */
  1018.  switch (pkt[0])
  1019.  {
  1020.  case PKT_POSS:
  1021.   BinaryPositionShort (&pkt[1]);
  1022.   break;
  1023.  
  1024.  case PKT_POSL:
  1025.   BinaryPositionLong (&pkt[1]);
  1026.   break;
  1027.  
  1028.  case PKT_PLAN:
  1029.   ServerBinaryPlanet (&pkt[1]);
  1030.   break;
  1031.  
  1032.  case PKT_VCNT:
  1033.   ServerBinaryVacant (&pkt[1]);
  1034.   break;
  1035.  
  1036.  case PKT_PING:
  1037.   ServerBinaryPing (&pkt[1]);
  1038.   break;
  1039.  
  1040.  default:
  1041.   Log ("ServerBinaryPacket: Unrecognized packet type: 0x%x",
  1042.    pkt[0]);
  1043.   break;
  1044.  }
  1045. }
  1046.  
  1047. void BinaryPositionShort (unsigned char *pkt)
  1048. /*
  1049.  *  Binary short position report
  1050.  */
  1051. {
  1052.  int c;
  1053.  double pos[3], vel[3];
  1054.  
  1055.  DecodeBinaryPacket (pkt, "cVV", &c, pos, vel);
  1056.  PositionShort (c, pos, vel);
  1057. }
  1058.  
  1059. void BinaryPositionLong (unsigned char *pkt)
  1060. /*
  1061.  *  Binary long position report
  1062.  */
  1063. {
  1064.  int c;
  1065.  double pos[3], vel[3], view[3], up[3];
  1066.  double move_up, move_down;
  1067.  double move_right, move_left, move_pitchright, move_pitchleft;
  1068.  
  1069.  DecodeBinaryPacket (pkt, "cVVvvffffff", &c, pos, vel, view, up,
  1070.   &move_up, &move_down, &move_right, &move_left,
  1071.   &move_pitchright, &move_pitchleft);
  1072.  
  1073.  PositionLong (c, pos, vel, view, up,
  1074.   move_up, move_down, move_right, move_left,
  1075.   move_pitchright, move_pitchleft);
  1076. }
  1077.  
  1078. void ServerBinaryVacant (char *pkt)
  1079. /*
  1080.  *  Server tells us which clients are in use
  1081.  */
  1082. {
  1083.  int c;
  1084.  unsigned int w, bit, i1, i2;
  1085.  
  1086.  /* Parse packet */
  1087.  DecodeBinaryPacket (pkt, "cc", &i1, &i2);
  1088.  w = i1 + 256*i2;
  1089.  
  1090.  /* See which bits are set */
  1091.  bit = 1;
  1092.  
  1093.  for (c=0; c<NCLIENTS; c++)
  1094.  {
  1095.   if (!(w & bit))
  1096.   {
  1097.    /* Don't bother if it's us (this should never happen!) */
  1098.    if (c == clientme.client)
  1099.    {
  1100.     Log ("ServerVacant: PANIC! Server says I am vacant!");
  1101.     return;
  1102.    }
  1103.  
  1104.    /* Destroy any associated target */
  1105.    if ((-1) != client[c].target) DestroyTarget (client[c].target);
  1106.    client[c].active = 0;
  1107.    client[c].target = (-1);
  1108.   }
  1109.  
  1110.   bit = bit * 2;
  1111.  }
  1112. }
  1113.